//! 用于zig的基础知识学习，如语法、类型等
//! @author XQ Lin
//! @email xqlin@qq.com
//!

const std = @import("std");
// NOTE：下面这种方式是一种很的实践
const print = std.debug.print;

// NOTE: 变量用 threadlocal 修饰，使得该变量在不同线程中是不同的
threadlocal var a_threadlocal: i32 = 1234;

fn practise_variable() void {
    std.debug.print("变量练习\n", .{});

    // 使用 const 作为关键字来声明常量，它无法再被更改，只有初次声明时可以赋值。
    const num: u16 = 17;
    print("常量是: {}\n", .{num});

    // destructure
    // 元组
    const tuple = .{ 1, 2, 3 };
    // NOTE：zig 不支持同时声明多个变量，如下：
    // var x, y, z = tuple;
    var x: u32 = undefined;
    var y: u32 = undefined;
    var z: u32 = undefined;
    x, y, z = tuple;
    print("tuple: x = {}, y = {}, z = {} \n", .{ x, y, z });
    // 数组
    const arr = [_]u32{ 4, 5, 6 }; // NOTE: _ 的使用
    x, y, z = arr;
    print("数组：x = {}, y = {}, z = {}\n", .{ x, y, z });
    // vector
    const vec: @Vector(3, u32) = .{ 7, 8, 9 };
    x, y, z = vec;
    print("Vector: x = {}, y = {}, z = {}\n", .{ x, y, z });

    // 块
    var a: i32 = 123;
    const b = blk: {
        a += 1;
        break :blk a;
    };
    print("块标签：{}\n", .{b});
}

fn thread_local() !void {
    const thread1 = try std.Thread.spawn(.{}, test_threadlocal, .{});
    const thread2 = try std.Thread.spawn(.{}, test_threadlocal, .{});
    test_threadlocal();
    thread1.join();
    thread2.join();
}

fn test_threadlocal() void {
    // 1234
    print("当前值是：{}\n", .{a_threadlocal});
    a_threadlocal += 1;
    // 1235
    print("加1的值:{}\n", .{a_threadlocal});
}

pub fn run() void {
    practise_variable();

    // NOTE: 调用类似 !void返回类型的函数，要么使用try传递错误，要么使用catch捕获。
    thread_local() catch |err| {
        print("线程错误：{}", .{err});
    };
}
